package com.sxf.mybatis.enhance.tools;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * 抽象类，用于实现所有Entity默认的各种方法
 * 
 * @author Administrator
 * 
 */
@SuppressWarnings("serial")
@XmlTransient
public abstract class DataObject implements IQueryableEntity {
	private transient Map<Field, Object> updateValueMap;

	protected transient boolean _recordUpdate = true;
	private transient String _rowid;

	private static final ConditionComparator cmp = new ConditionComparator();

	public final void startUpdate() {
		_recordUpdate = true;
	}

	public final void stopUpdate() {
		_recordUpdate = false;
	}

	public final boolean hasQuery() {
		return null != null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.IQueryableEntity#isUsed(jef.database.Field)
	 */
	public final boolean isUsed(Field field) {
		if (updateValueMap == null)
			return false;
		return updateValueMap.containsKey(field);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#clearUpdate()
	 */
	public final void clearUpdate() {
		updateValueMap = null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#getUpdateValueMap()
	 */
	@SuppressWarnings("unchecked")
	public final Map<Field, Object> getUpdateValueMap() {
		if (updateValueMap == null)
			return Collections.EMPTY_MAP;
		return updateValueMap;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#prepareUpdate(jef.database.Field,
	 * java.lang.Object)
	 */
	public final void prepareUpdate(Field field, Object newValue) {
		prepareUpdate(field, newValue, false);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#prepareUpdate(jef.database.Field,
	 * java.lang.Object, boolean)
	 */
	public final void prepareUpdate(Field field, Object newValue, boolean force) {
		Map<String, Object> ba = new HashMap<String, Object>();
		String fieldName = field.name();
		if (updateValueMap == null)
			updateValueMap = new TreeMap<Field, Object>(cmp);
		if (force || !ObjectUtils.equals(ba.get(fieldName), newValue)) {
			updateValueMap.put(field, newValue);
		}
		return;
	}

	void markUpdateFlag(Field field, Object newValue) {
		if (updateValueMap == null) {
			updateValueMap = new TreeMap<Field, Object>(cmp);
			updateValueMap.put(field, newValue);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#applyUpdate()
	 */
	public final void applyUpdate() {
		if (updateValueMap == null)
			return;

		Map<String, Object> ba = new HashMap<String, Object>();

		for (Entry<Field, Object> entry : updateValueMap.entrySet()) {
			Object newValue = entry.getValue();
			if (newValue instanceof Field) {
				continue;
			}
			ba.put(entry.getKey().name(), newValue);
		}
		clearUpdate();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jef.database.query.UpdateAble#needUpdate()
	 */
	public final boolean needUpdate() {
		return (updateValueMap != null) && this.updateValueMap.size() > 0;
	}

	public String rowid() {
		return _rowid;
	}

	public void bindRowid(String rowid) {
		this._rowid = rowid;
	}

	/*
	 * 供子类hashCode（）方法调用，判断内嵌的hashCode方法是否可用
	 */
	protected final int getHashCode() {
		return new HashCodeBuilder().append("").append(_recordUpdate)
				.append(updateValueMap).toHashCode();
	}

	private static class ConditionComparator implements Comparator<Field>,
			Serializable {
		public int compare(Field o1, Field o2) {
			if (o1 == o2)
				return 0;
			if (o1 == null)
				return 1;
			if (o2 == null)
				return -1;
			return o1.name().compareTo(o2.name());
		}
	}
}
